/**************************************************************************//**
* @file     ECULockControl.c
* @brief    ECU Lock Control
* @author   Jungle Wang
* @date     2022/5/10
* @version  1
*******************************************************************************
* Copyright (c) DeltaTec 2016
* All right reserved.
******************************************************************************/

/******************************************************************************
* COMPILATION OPTION
******************************************************************************/

/******************************************************************************
* INCLUDE FILE
******************************************************************************/
// Include system file

// Include project file
//#include "GlobalVariables.h"
#include "ECULockControl.h"
#include "ECULockLib.h"
#include "Eeprom.h"
#include "CAN.h"
#include "r_cg_can.h"
#include "fet.h"
#include "Main.h"
#include "nvm.h"
//#include "Configure.h"
#define PET_WATCHDOG    {R_WDT_Restart();}


/*************************************************************************//**
* @detials


******************************************************************************/

/******************************************************************************
* DEFINE DESCRIPTION
******************************************************************************/

/******************************************************************************
* ENUM DESCRIPTION
******************************************************************************/

/******************************************************************************
* STRUCTURE DESCRIPTION
******************************************************************************/




/******************************************************************************
* VARIABLE DESCRIPTION
******************************************************************************/
UINT32 ECULockLibRandomCode;
UINT32 ECULockLibKeyCode,ECULockLibKeyCodeSave;
UINT8  ECULockLibMatchResult;
BOOL   bReadECULockLibRandomCodeFlag,bWriteECULockLibKeyCodeFlag;
BOOL   bECULockLibInit=0;



/*************************************************************************//**
* @ingroup user_interface
* @brief
* @note    none
* @param   none
* @return  none
*****************************************************************************/




/*************************************************************************//**
* @ingroup configure
* @brief   This function read the lock value from EEPROM and loads it
*          into the variable lift_lockset.
* @param   none
* @return  none
*****************************************************************************/
void vLoadLiftLockSet(void)
{
    UINT16 u16_lockoption;
    EEPROM_ERR en_block_error;

    // read lockset from section
    en_block_error = record_read(RECORD_MAGIC_LIFT_LOCKSET, 2, (UINT8 *)&u16_lockoption);

    // if section is correct, use it
    if (EEPROM_OK == en_block_error)
    {
        unLiftlocksets.word = u16_lockoption;
    }

    //read lock or unlock lift state
    MAIN_Data.bSemiLockMachine =((stECULockLibStored.u8LockLibStatus[3]==1) || (stECULockLibStored.u8LockLibStatus[3] ==2))?1:0;
    //when this flag is 1, need to send to HMI,display "The Lift is Initiative locked"
    MAIN_Data.bPassiveLockMachine = (stECULockLibStored.u8LockLibStatus[4]==0x01)?1:0;
    //when this flag is 1, need to send to HMI,display "The Lift is Passive locked"
    MAIN_Data.bTempUnLockMachine = (stECULockLibStored.u8LockLibStatus[5]==0x01)?1:0;
    //when this flag is 1, need to send to HMI,display "The Lift is Temp Unlock"

    unLiftlocksets.bit.bBindFlag = (stECULockLibStored.u8LockLibStatus[2]==0x01)?1:0;

    if (MAIN_Data.bTempUnLockMachine == 1 || GPS_ENABLE_FLAG == 0 || GPS_ENABLE_FLAG == 58)
    {
        MAIN_Data.bSemiLockMachine = 0;
        MAIN_Data.bPassiveLockMachine = 0;
    }

    //send to HMI display

    //unFaultWordMi.bit.bSemiLockMachine = MAIN_Data.bSemiLockMachine;
    //unFaultWordMi.bit.bPassiveLockMachine = MAIN_Data.bPassiveLockMachine;
    //unFaultWordMi.bit.bTempUnLockMachine = MAIN_Data.bTempUnLockMachine;

}


/*************************************************************************//**
* @ingroup vGetECULockLibData
* @brief   It get ECULockLibData from EEPROM or restore default.
* @param   none
* @return  none
*****************************************************************************/
UINT8 u8CheckECULockLibData(UINT8 u8RecordMagicc1,UINT8 u8RecordMagicc2,UINT8 *pAppNvmData)
{
	UINT8 ret=0;
	UINT8 i=0,j=0;
	UINT8 Arr1[48]={0};
	UINT8 Arr2[48]={0};
	ret = 0;
	if (EEPROM_OK != record_read(u8RecordMagicc1, 48, &Arr1[0]))
	{
		ret |= 1;
	}
	if (EEPROM_OK != record_read(u8RecordMagicc2, 48, &Arr2[0]))
	{
		ret |= (1<<1);
	}
	if(ret == 0)
	{
		j=0;
		for(i=0;i<48;i++)
		{
			if(Arr1[i]!=Arr2[i])
			{
				j++;
			}
		}
		if(j!=0)
		{
			ret |= (1<<2);
		}
	}
	if(ret == 0)
	{
		for(i=0;i<48;i++)
		{
			pAppNvmData[i] = Arr1[i];
		}
	}
	return ret;
}
void vGetECULockLibData(void)
{	
	u8 u8RetryCnt=0;
	u8 u8ReadOkFlag = 0;
	u8 u8Temp=0;
	u8ReadOkFlag = 0;
	for(u8RetryCnt = 0;u8RetryCnt<3 ;u8RetryCnt++)
	{
		u8Temp = 0xff;
		if(u8Temp!=0)
		{
			u8Temp = u8CheckECULockLibData(RECORD_MAGIC_ECULOCKLIB_DATA1,RECORD_MAGIC_ECULOCKLIB_DATA2,&stECULockLibStored.u8LockLibData[0]);
			if(u8Temp == 0)
			{
				u8ReadOkFlag |= 1; 
			}
			PET_WATCHDOG;
		}
		if(u8Temp!=0)
		{
			u8Temp = u8CheckECULockLibData(RECORD_MAGIC_ECULOCKLIB_DATA1,RECORD_MAGIC_ECULOCKLIB_DATA3,&stECULockLibStored.u8LockLibData[0]);
			if(u8Temp == 0)
			{
				u8ReadOkFlag |= (1<<1); 
			}
			PET_WATCHDOG;
		}
		if(u8Temp!=0)
		{
			u8Temp = u8CheckECULockLibData(RECORD_MAGIC_ECULOCKLIB_DATA1,RECORD_MAGIC_ECULOCKLIB_DATA4,&stECULockLibStored.u8LockLibData[0]);
			if(u8Temp == 0)
			{
				u8ReadOkFlag |= (1<<2); 
			}
			PET_WATCHDOG;
		}
		if(u8Temp!=0)
		{
			u8Temp = u8CheckECULockLibData(RECORD_MAGIC_ECULOCKLIB_DATA2,RECORD_MAGIC_ECULOCKLIB_DATA3,&stECULockLibStored.u8LockLibData[0]);
			if(u8Temp == 0)
			{
				u8ReadOkFlag |= (1<<3); 
			}
			PET_WATCHDOG;
		}
		if(u8Temp!=0)
		{
			u8Temp = u8CheckECULockLibData(RECORD_MAGIC_ECULOCKLIB_DATA2,RECORD_MAGIC_ECULOCKLIB_DATA4,&stECULockLibStored.u8LockLibData[0]);
			if(u8Temp == 0)
			{
				u8ReadOkFlag |= (1<<4); 
			}
			PET_WATCHDOG;
		}
		if(u8Temp!=0)
		{
			u8Temp = u8CheckECULockLibData(RECORD_MAGIC_ECULOCKLIB_DATA3,RECORD_MAGIC_ECULOCKLIB_DATA4,&stECULockLibStored.u8LockLibData[0]);
			if(u8Temp == 0)
			{
				u8ReadOkFlag |= (1<<5); 
			}
			PET_WATCHDOG;
		}
		if(u8Temp == 0)
		{
			break;
		}
	}
}

/*************************************************************************//**
* @ingroup ECULockLib_CANRx
* @brief   receive data from can,if ID true,put array data into lib
* @param   none
* @return  none
*****************************************************************************/
void vECULockLib_CANRx(void)
{
    //if ID low ==4A,put the array data[13] into lib,one data only run once
    //not 54A
    if ((stECULockLibCANdata.au8ECULockCANRXData[1] == 0x4A)&&((stECULockLibCANdata.au8ECULockCANRXData[2] == 0x02)||(stECULockLibCANdata.au8ECULockCANRXData[2] == 0x03)||(stECULockLibCANdata.au8ECULockCANRXData[2] == 0x04)))
        //if (stECULockLibCANdata.au8ECULockCANRXData[1] == 0x4A)
    {
        n_ECULockLibInjectCAN(&stECULockLibCANdata.au8ECULockCANRXData[0]);
        stECULockLibCANdata.au8ECULockCANRXData[1] = 0x00;
    }


}

/*************************************************************************//**
* @ingroup ECULockLib_CANTx
* @brief   if need to send data by can,send data from CANID_DATA_OUT
* @param   none
* @return  none
*****************************************************************************/
void vECULockLib_CANTx(void)
{
    UINT16 u16_id_hi, u16_id_lo;
    UINT8  u8_buffer[8];
    UINT8  i;
    //if need to send data by can,send data from CANID_DATA_OUT
    if (LibStatus.Flag_CANToSend == 0x01)
    {
        u16_id_hi = (UINT16)LibStatus.CANID_DATA_OUT[4] << 8 | (UINT16)LibStatus.CANID_DATA_OUT[3];
        u16_id_lo = (UINT16)LibStatus.CANID_DATA_OUT[2] << 8 | (UINT16)LibStatus.CANID_DATA_OUT[1];
        for(i=0; i<8; i++)
        {
            u8_buffer[i] = LibStatus.CANID_DATA_OUT[5+i];
        }
        R_CAN0_Send(u16_id_hi, u16_id_lo, 8, u8_buffer);
        n_ECULockLibSetSentSTA(0x00);
    }


}

/*************************************************************************//**
* @ingroup ECULockLib_CommandRx
* @brief   receive cmd from lib,if  true,put array data into eeprom
* @param   none
* @return  none
*****************************************************************************/
#define SaveGPS_ECULOCKLIBOverTime	(500/100)
void vECULockLib_CommandRx(void)
{
	static UINT8 u8State = 0,u8_DelayCnt=0;
	//if Flag_CMDToRSV ==1,put the array data[48] into eeprom
	if (LibStatus.Flag_CMDToRSV == 1 && u8State!=1)
	{
		n_ECULockLibGetLockParas(&stECULockLibStored.u8LockLibData[0]);
		u8State = 1;
		u8_DelayCnt = 0;
		NVM_SaveGPS_ECULOCKLIB();
	}
	
	if(u8State == 1)
	{
		if(u8_DelayCnt < SaveGPS_ECULOCKLIBOverTime)
		{
			u8_DelayCnt++;
			if(u8Is_NVM_SaveGPS_ECULOCKLIB_Writed() == 0)
			{
				n_ECULockLibSetRSVSTA(0x00);
				u8State = 0;
			}
		}
		else
		{
			n_ECULockLibSetRSVSTA(0x01);
			u8State = 0;
		}
	}
	
}

/*
void vECULockLib_CommandRx(void)
{
    //if Flag_CMDToRSV ==1,put the array data[48] into eeprom
    if (LibStatus.Flag_CMDToRSV == 1)
    {
        n_ECULockLibGetLockParas(&stECULockLibStored.u8LockLibData[0]);
        if (EEPROM_OK == record_write(RECORD_MAGIC_ECULOCKLIB_DATA1, 48, &stECULockLibStored.u8LockLibData[0]))
            n_ECULockLibSetRSVSTA(0x00);
        else
            n_ECULockLibSetRSVSTA(0x01);
    }

}
*/

/*************************************************************************//**
* @ingroup ECULockLib_BindSet
* @brief   receive Flag_BindToDo from lib,if ID true,put array data into lib
* @param   none
* @return  none
*****************************************************************************/
void vECULockLib_BindSet(void)
{
    if ((LibStatus.Flag_BindToDo == 0x01)||(LibStatus.Flag_BindToDo == 0x02))
    {
        n_ECULockLibSetBindSTA(LibStatus.Flag_BindToDo,0x00);
    }

}

/*************************************************************************//**
* @ingroup ECULockLib_LockandUnlock
* @brief   LockandUnlock logic
* @param   none
* @return  none
*****************************************************************************/
void vECULockLib_LockandUnlock(void)
{
    UINT8 u8First_lock,u8Sencond_lock;
    u8First_lock = unLiftlocksets.bit.bFirstLockLift;
    u8Sencond_lock = unLiftlocksets.bit.bSecondLockLift;
    if(LibStatus.Flag_LockToDo == 0x02)
    {
        unLiftlocksets.bit.bFirstLockLift = 1;
        //if(!(unFets.word & (FET_MCE | FET_MCE2)))
        {
            MAIN_Data.bSemiLockMachine = 1;
            n_ECULockLibSetLockSTA(0x02,0x00);
        }
    }
    else if(LibStatus.Flag_LockToDo == 0x03)
    {
        unLiftlocksets.bit.bSecondLockLift = 1;
        //if(!(unFets.word & (FET_MCE | FET_MCE2)))
        {
            MAIN_Data.bSemiLockMachine = 1;
            n_ECULockLibSetLockSTA(0x03,0x00);
        }
    }
    else if(LibStatus.Flag_LockToDo == 0x01)
    {
        unLiftlocksets.bit.bFirstLockLift = 0;
        unLiftlocksets.bit.bSecondLockLift = 0;
        MAIN_Data.bSemiLockMachine = 0;
        n_ECULockLibSetLockSTA(0x01,0x00);
    }
	
	if(GPS_ENABLE_FLAG == 0 || GPS_ENABLE_FLAG == 58)
	{
		unLiftlocksets.bit.bFirstLockLift = 0;
        unLiftlocksets.bit.bSecondLockLift = 0;
        MAIN_Data.bSemiLockMachine = 0;
        n_ECULockLibSetLockSTA(0x01,0x00);
	}
	
    //save to eeprom
    if((u8First_lock != unLiftlocksets.bit.bFirstLockLift) ||
       (u8Sencond_lock != unLiftlocksets.bit.bSecondLockLift))
        NVM_SaveGpsLockOrUnlockLift();

    //send to HMI
    //unFaultWordMi.bit.bSemiLockMachine = stMainData.bSemiLockMachine;
}

/*************************************************************************//**
* @ingroup ECULockLib_PassiveLock
* @brief   Passivelock logic
* @param   none
* @return  none
*****************************************************************************/
void vECULockLib_PassiveLock(void)
{
    if(LibStatus.Flag_PassiveLockToDo == 0x03 || GPS_ENABLE_FLAG == 0 || GPS_ENABLE_FLAG == 58)
    {
        unLiftlocksets.bit.bPassiveLockLift = 0;//don't need save,only used to monitor
        MAIN_Data.bPassiveLockMachine = 0;
        n_ECULockLibSetPassiveLockSTA(0x03,0x00);
    }
    else if(LibStatus.Flag_PassiveLockToDo == 0x04)
    {
        //if(!(unFets.word & (FET_MCE | FET_MCE2)))
        {
            MAIN_Data.bPassiveLockMachine = 1;
            unLiftlocksets.bit.bPassiveLockLift = 1;
            n_ECULockLibSetPassiveLockSTA(0x04,0x00);
        }

    }
    //when after tempunlock time is off,the bTempUnLockMachine flag is be set
    MAIN_Data.bTempUnLockMachine = (stECULockLibStored.u8LockLibStatus[5]==0x01)?1:0;
    //unFaultWordMi.bit.bTempUnLockMachine = stMainData.bTempUnLockMachine;
    //send to HMI
   // unFaultWordMi.bit.bPassiveLockMachine = stMainData.bPassiveLockMachine;
    MAIN_Data.bSemiLockMachine =((stECULockLibStored.u8LockLibStatus[3]==1) || (stECULockLibStored.u8LockLibStatus[3] ==2))?1:0;
    if (MAIN_Data.bTempUnLockMachine == 1 || GPS_ENABLE_FLAG == 0 || GPS_ENABLE_FLAG == 58)
    {
        MAIN_Data.bSemiLockMachine = 0;
        MAIN_Data.bPassiveLockMachine = 0;
    }
    //unFaultWordMi.bit.bSemiLockMachine = stMainData.bSemiLockMachine;
}

/*************************************************************************//**
* @ingroup ECULockLib_TempUnLock
* @brief   TempUnLock logic
* @param   none
* @return  none
*****************************************************************************/
void vECULockLib_TempUnLock(void)
{
    //only when in temp lock interface,run n_ECULockLibTempLockRandomMake
    if(bReadECULockLibRandomCodeFlag ==1)
    {
        ECULockLibRandomCode = n_ECULockLibTempLockRandomMake();
        bReadECULockLibRandomCodeFlag = 0;
    }
    //send ECULockLibRandomCode to HMI
    //then return code to M
    //only when enter the keycode ,run n_ECULockLibTempLockSigIn
    if(bWriteECULockLibKeyCodeFlag ==1)
    {
        ECULockLibMatchResult = n_ECULockLibTempLockSigIn(ECULockLibKeyCode);
        bWriteECULockLibKeyCodeFlag =0;
    }
    //send ECULockLibMatchResult to HMI


}

/*************************************************************************//**
* @ingroup ECULockLib_SaveData
* @brief   receive cmd from lib,if  true,put array data into eeprom
* @param   none
* @return  none
*****************************************************************************/
void vECULockLib_SaveData(void)
{
    //Every 1 min,put the array data[48] into eeprom
    n_ECULockLibGetLockParas(&stECULockLibStored.u8LockLibData[0]);
    //record_write(RECORD_MAGIC_ECULOCKLIB_DATA1, 48, &stECULockLibStored.u8LockLibData[0]);
	NVM_SaveGPS_ECULOCKLIB();
}


/*************************************************************************//**
* @ingroup ECULockLib_Init
* @brief   Init ECULockLib.
* @param   none
* @return  none
*****************************************************************************/
UINT32 U32_ECULOCK_LIB_RecoveryCnt=0;
void vGetLibRecoveryCnt(void)
{
	UINT8 i=0;
	for(i=0;i<3;i++)
	{
		if (EEPROM_OK == record_read(RECORD_MAGIC_ECULOCKLIB_DATA_RecoveryCnt, 4, &U32_ECULOCK_LIB_RecoveryCnt))
		{
			break;
		}
	}
	if(i == 3)
	{
		U32_ECULOCK_LIB_RecoveryCnt=0;
	}
}
UINT8 u8LibReadCnt=0;
void vECULockLib_Init(void)
{
	//UINT8 i=0;
    //get lock value from EEPROM
    //get ECULockLibData from EEPROM
    vGetECULockLibData();
	vGetLibRecoveryCnt();
    //put ECULockLibData from EEPROM into ECULockLib
    /*
    if(0 != n_ECULockLibInit(&stECULockLibStored.u8LockLibData[0]))
    {
        n_ECULockLibParasRecovery();
    }*/
    for(u8LibReadCnt=0;u8LibReadCnt<3;u8LibReadCnt++)
    {
		if(0 != n_ECULockLibInit(&stECULockLibStored.u8LockLibData[0]))
	    {
	        vGetECULockLibData();
	    }
		else
		{
			break;
		}
	}
	if(u8LibReadCnt == 3)
	{
		U32_ECULOCK_LIB_RecoveryCnt++;
		record_write_verify(RECORD_MAGIC_ECULOCKLIB_DATA_RecoveryCnt, 4, &U32_ECULOCK_LIB_RecoveryCnt);
		if(U32_ECULOCK_LIB_RecoveryCnt == 2)
		{
			record_write_verify(RECORD_MAGIC_ECULOCKLIB_DATA_BeforeRecovery, 48, &stECULockLibStored.u8LockLibData[0]);
		}
		n_ECULockLibParasRecovery();
	}
    //ECULockLib Status
    n_ECULockLibGetStatus(&stECULockLibStored.u8LockLibStatus[0]);
    vLoadLiftLockSet();
    n_ECULockLibSetPassiveLockDelayTime(30);

}

/*************************************************************************//**
* @ingroup ECULockLib_Statement
* @brief   ECULockLib main process,need cycle 100ms call .
* @param   none
* @return  none
*****************************************************************************/
void vECULockLib_Statement(void)
{
    //move to main init
    /*if(bECULockLibInit ==0)
    {
        vECULockLib_Init();
        bECULockLibInit =1;
    }*/
    //cycle call lib main function
    n_ECULockLibProcess(100);
    //cycle call lock delay time
    if(Fets.word & (FET_MCE | FET_MCE2))
        n_ECULockLibLockDelayTiming(100);
    //if lib is error ,init lib
    //if(LibStatus.LibRunSTA != 0)
    //vECULockLib_Init();
    //every 1min,save 48 data
  //  if((stTimerData.u32SystemClock_ms % 60000) == 0)
   	if(stHourMeter.u32Fraction - stHourMeter.u32FractionSave >= 20) //72s
   	{
   		stHourMeter.u32FractionSave = stHourMeter.u32Fraction;
        vECULockLib_SaveData();
   	}
    //CAN receive and send
    vECULockLib_CANRx();
    vECULockLib_CANTx();
    //CMD receive
    vECULockLib_CommandRx();
    //Tbox and ECU bind
    vECULockLib_BindSet();
    //ECULockLib Status
    n_ECULockLibGetStatus(&stECULockLibStored.u8LockLibStatus[0]);
    n_ECULockLibGetLockParas(&stECULockLibStored.u8LockLibData[0]);
    //LockandUnlock logic
    vECULockLib_LockandUnlock();
    //PassiveLock logic
    vECULockLib_PassiveLock();
    //if TBOX not on line,4gstate set 1
    if (LibStatus.TBOXHandShakeSTA ==4)
        stECULockLibCANdata.u8GPS4gState = 1;
    //
    if ((MAIN_Data.bTempUnLockMachine ==1) && (stECULockLibCANdata.u8GPS4gState ==1) && (LibStatus.TBOXHandShakeSTA ==3))
        n_ECULockLibTempLockCancel();
    //TempUnLock logic
    //when HMI operate menu to TempUnlock interface
    #if 0
    if(MAIN_Data.eState == MAIN_SPEED_ADJUST)
    {
        if(((stECULockLibCANdata.u8GPS4gState ==0)&&(unLiftlocksets.bit.bFirstLockLift||unLiftlocksets.bit.bSecondLockLift))
           ||((MAIN_Data.bPassiveLockMachine ==1)))
            vECULockLib_TempUnLock();
    }
	#endif


}

#define ECU_LOCK_CYCLE    100        // milliseconds.
#define ECU_LOCK_RATE    ((ECU_LOCK_CYCLE/SYSTEM_CYCLE) - 1)
void ECULockControlProcess(void)
{
	static UINT8 u8_count = ECU_LOCK_RATE;
	
	if(u8_count)
    {
        u8_count--;
    }
    else
    {
		u8_count = ECU_LOCK_RATE;
		vECULockLib_Statement();
	}
}
/******************************************************************************
* End of module
******************************************************************************/
